from fastapi import APIRouter, Depends, HTTPException, status
from sqlalchemy.orm import Session
from datetime import datetime, timedelta
from app.database import get_db
from app import models, schemas, auth
from app.sms_service import sms_provider
from app.redis_client import get_redis
import logging

router = APIRouter(prefix="/auth", tags=["认证"])
logger = logging.getLogger(__name__)


@router.post("/send_code", response_model=schemas.Response)
async def send_code(request: schemas.SendCodeRequest, db: Session = Depends(get_db)):
    """发送短信验证码"""
    redis = get_redis()
    
    # 检查是否在限流期间
    throttle_key = f"sms_throttle:{request.phone}"
    if redis.exists(throttle_key):
        raise HTTPException(status_code=429, detail="发送过于频繁，请稍后再试")
    
    # 生成6位数字验证码（100000-999999）
    code = auth.generate_sms_code()
    
    # 发送短信
    success = await sms_provider.send_code(request.phone, code, request.purpose)
    if not success:
        raise HTTPException(status_code=500, detail="短信发送失败")
    
    # 保存原始验证码到数据库（不加密）
    expire_at = datetime.utcnow() + timedelta(minutes=5)
    sms_code = models.SMSCode(
        phone=request.phone,
        code=code,  # 直接存储原始验证码
        purpose=request.purpose,
        expire_at=expire_at
    )
    db.add(sms_code)
    db.commit()
    
    # 设置限流（60秒内不能重复发送）
    redis.setex(throttle_key, 60, "1")
    
    return schemas.Response(message="验证码已发送")


@router.post("/register", response_model=schemas.Response)
async def register(request: schemas.RegisterRequest, db: Session = Depends(get_db)):
    """用户注册"""
    # 检查手机号是否已注册
    existing_user = db.query(models.User).filter(models.User.phone == request.phone).first()
    if existing_user:
        raise HTTPException(status_code=400, detail="该手机号已注册")
    
    # 验证验证码
    sms_code = db.query(models.SMSCode).filter(
        models.SMSCode.phone == request.phone,
        models.SMSCode.purpose == "register",
        models.SMSCode.expire_at > datetime.utcnow()
    ).order_by(models.SMSCode.created_at.desc()).first()
    
    if not sms_code:
        raise HTTPException(status_code=400, detail="验证码不存在或已过期")
    
    # 直接比较验证码（不加密）
    if not auth.verify_sms_code(request.code, sms_code.code):
        sms_code.attempts += 1
        db.commit()
        raise HTTPException(status_code=400, detail="验证码错误")
    
    # 设置默认密码为 123456
    default_password = "123456"
    password_hash = auth.get_password_hash(default_password)
    
    # 创建用户
    user = models.User(
        phone=request.phone,
        password_hash=password_hash,
        nickname=request.nickname or f"用户{request.phone[-4:]}",
        status="active"
    )
    db.add(user)
    db.commit()
    db.refresh(user)
    
    # 删除已使用的验证码
    db.delete(sms_code)
    db.commit()
    
    # 生成token
    token = auth.create_access_token(data={"sub": user.id})
    auth.save_token_to_redis(user.id, token)
    
    return schemas.Response(
        message="注册成功，默认密码为123456，请及时修改",
        data=schemas.TokenResponse(access_token=token)
    )


@router.post("/login/code", response_model=schemas.Response)
async def login_with_code(request: schemas.LoginCodeRequest, db: Session = Depends(get_db)):
    """验证码登录"""
    # 查找用户
    user = db.query(models.User).filter(models.User.phone == request.phone).first()
    if not user:
        raise HTTPException(status_code=400, detail="用户不存在")
    
    # 验证验证码
    sms_code = db.query(models.SMSCode).filter(
        models.SMSCode.phone == request.phone,
        models.SMSCode.purpose == "login",
        models.SMSCode.expire_at > datetime.utcnow()
    ).order_by(models.SMSCode.created_at.desc()).first()
    
    if not sms_code:
        raise HTTPException(status_code=400, detail="验证码不存在或已过期")
    
    # 直接比较验证码（不加密）
    if not auth.verify_sms_code(request.code, sms_code.code):
        sms_code.attempts += 1
        db.commit()
        raise HTTPException(status_code=400, detail="验证码错误")
    
    # 删除已使用的验证码
    db.delete(sms_code)
    db.commit()
    
    # 生成token
    token = auth.create_access_token(data={"sub": user.id})
    auth.save_token_to_redis(user.id, token)
    
    return schemas.Response(
        message="登录成功",
        data=schemas.TokenResponse(access_token=token)
    )


@router.post("/login/password", response_model=schemas.Response)
async def login_with_password(request: schemas.LoginPasswordRequest, db: Session = Depends(get_db)):
    """密码登录"""
    # 查找用户
    user = db.query(models.User).filter(models.User.phone == request.phone).first()
    if not user:
        raise HTTPException(status_code=400, detail="用户不存在")
    
    # 验证密码
    if not auth.verify_password(request.password, user.password_hash):
        raise HTTPException(status_code=400, detail="密码错误")
    
    # 生成token
    token = auth.create_access_token(data={"sub": user.id})
    auth.save_token_to_redis(user.id, token)
    
    return schemas.Response(
        message="登录成功",
        data=schemas.TokenResponse(access_token=token)
    )


@router.post("/logout", response_model=schemas.Response)
async def logout(current_user: models.User = Depends(auth.get_current_user)):
    """退出登录"""
    auth.delete_token_from_redis(current_user.id)
    return schemas.Response(message="退出成功")


@router.post("/password/set", response_model=schemas.Response)
async def set_password(
    request: schemas.SetPasswordRequest,
    current_user: models.User = Depends(auth.get_current_user),
    db: Session = Depends(get_db)
):
    """设置密码（首次登录）"""
    current_user.password_hash = auth.get_password_hash(request.new_password)
    db.commit()
    return schemas.Response(message="密码设置成功")


@router.post("/password/change", response_model=schemas.Response)
async def change_password(
    request: schemas.ChangePasswordRequest,
    current_user: models.User = Depends(auth.get_current_user),
    db: Session = Depends(get_db)
):
    """修改密码"""
    # 验证旧密码
    if not auth.verify_password(request.old_password, current_user.password_hash):
        raise HTTPException(status_code=400, detail="旧密码错误")
    
    # 更新密码
    current_user.password_hash = auth.get_password_hash(request.new_password)
    db.commit()
    return schemas.Response(message="密码修改成功")


@router.post("/password/reset", response_model=schemas.Response)
async def reset_password(request: schemas.ResetPasswordRequest, db: Session = Depends(get_db)):
    """重置密码"""
    # 验证验证码
    sms_code = db.query(models.SMSCode).filter(
        models.SMSCode.phone == request.phone,
        models.SMSCode.purpose == "reset",
        models.SMSCode.expire_at > datetime.utcnow()
    ).order_by(models.SMSCode.created_at.desc()).first()
    
    if not sms_code:
        raise HTTPException(status_code=400, detail="验证码不存在或已过期")
    
    # 直接比较验证码（不加密）
    if not auth.verify_sms_code(request.code, sms_code.code):
        sms_code.attempts += 1
        db.commit()
        raise HTTPException(status_code=400, detail="验证码错误")
    
    # 查找用户
    user = db.query(models.User).filter(models.User.phone == request.phone).first()
    if not user:
        raise HTTPException(status_code=400, detail="用户不存在")
    
    # 更新密码
    user.password_hash = auth.get_password_hash(request.new_password)
    
    # 删除已使用的验证码
    db.delete(sms_code)
    db.commit()
    
    return schemas.Response(message="密码重置成功")

